"""
容器Override测试
===============

测试依赖注入容器的Override功能，确保测试时可以正确替换依赖
"""

import pytest
from unittest.mock import Mock, AsyncMock
from dependency_injector import providers

from containers.test_container import TestContainer as Container
# Mock services for testing
from unittest.mock import Mock

# Service classes将通过Mock创建
class CacheService:
    """Cache service mock for testing"""
    pass

class WebSocketService:
    """WebSocket service mock for testing"""
    pass

class MarketDataService:
    """Market data service mock for testing"""
    pass


class TestContainerOverride:
    """容器Override测试类"""
    
    @pytest.fixture
    def container(self):
        """创建测试容器"""
        container = Container()
        container.config.from_dict({
            "environment": "testing",
            "market_data_db_url": "sqlite:///test.db",
            "redis_url": "redis://localhost:6379/1",
        })
        return container
    
    def test_container_creation(self, container):
        """测试容器创建"""
        assert container is not None
        assert container.config.environment() == "testing"
    
    def test_override_cache_service(self, container):
        """测试Override缓存服务"""
        # 创建Mock缓存服务
        mock_cache_service = Mock(spec=CacheService)
        mock_cache_service.get = AsyncMock(return_value=None)
        mock_cache_service.set = AsyncMock(return_value=True)
        
        # Override容器中的缓存服务
        with container.cache_service.override(providers.Object(mock_cache_service)):
            # 获取服务实例
            cache_service = container.cache_service()
            
            # 验证Override成功
            assert cache_service is mock_cache_service
            assert hasattr(cache_service, 'get')
            assert hasattr(cache_service, 'set')
    
    def test_override_websocket_service(self, container):
        """测试Override WebSocket服务"""
        # 创建Mock WebSocket服务
        mock_ws_service = Mock(spec=WebSocketService)
        mock_ws_service.connect = AsyncMock()
        mock_ws_service.disconnect = AsyncMock()
        mock_ws_service.broadcast = AsyncMock()
        
        # Override容器中的WebSocket服务
        with container.websocket_service.override(providers.Object(mock_ws_service)):
            # 获取服务实例
            ws_service = container.websocket_service()
            
            # 验证Override成功
            assert ws_service is mock_ws_service
            assert hasattr(ws_service, 'connect')
            assert hasattr(ws_service, 'broadcast')
    
    def test_override_market_data_service(self, container):
        """测试Override市场数据服务"""
        # 创建Mock市场数据服务
        mock_market_service = Mock(spec=MarketDataService)
        mock_market_service.get_real_time_data = AsyncMock(return_value={})
        mock_market_service.get_stock_list = AsyncMock(return_value=[])
        
        # Override容器中的市场数据服务
        with container.market_data_service.override(providers.Object(mock_market_service)):
            # 获取服务实例
            market_service = container.market_data_service()
            
            # 验证Override成功
            assert market_service is mock_market_service
            assert hasattr(market_service, 'get_real_time_data')
            assert hasattr(market_service, 'get_stock_list')
    
    def test_multiple_overrides(self, container):
        """测试多个服务同时Override"""
        # 创建多个Mock服务
        mock_cache = Mock(spec=CacheService)
        mock_websocket = Mock(spec=WebSocketService)
        mock_market_data = Mock(spec=MarketDataService)
        
        # 同时Override多个服务
        with container.cache_service.override(providers.Object(mock_cache)), \
             container.websocket_service.override(providers.Object(mock_websocket)), \
             container.market_data_service.override(providers.Object(mock_market_data)):
            
            # 验证所有服务都被正确Override
            assert container.cache_service() is mock_cache
            assert container.websocket_service() is mock_websocket  
            assert container.market_data_service() is mock_market_data
    
    def test_override_scope_isolation(self, container):
        """测试Override作用域隔离"""
        # 获取原始服务
        original_cache = container.cache_service()
        
        # 创建Mock服务
        mock_cache = Mock(spec=CacheService)
        
        # 在Override作用域内
        with container.cache_service.override(providers.Object(mock_cache)):
            overridden_cache = container.cache_service()
            assert overridden_cache is mock_cache
            assert overridden_cache is not original_cache
        
        # Override作用域外，应该恢复原始服务
        restored_cache = container.cache_service()
        # 注意：由于容器可能重新创建实例，我们检查类型而不是实例相等性
        assert type(restored_cache) == type(original_cache)
    
    @pytest.mark.asyncio
    async def test_override_with_async_methods(self, container):
        """测试Override异步方法"""
        # 创建Mock服务，包含异步方法
        mock_cache = Mock(spec=CacheService)
        mock_cache.get = AsyncMock(return_value="test_value")
        mock_cache.set = AsyncMock(return_value=True)
        
        # Override缓存服务
        with container.cache_service.override(providers.Object(mock_cache)):
            cache_service = container.cache_service()
            
            # 测试异步方法调用
            result = await cache_service.get("test_key")
            assert result == "test_value"
            mock_cache.get.assert_called_once_with("test_key")
            
            success = await cache_service.set("test_key", "test_value")
            assert success is True
            mock_cache.set.assert_called_once_with("test_key", "test_value")
    
    def test_override_configuration(self, container):
        """测试Override配置"""
        # Override配置
        test_config = {
            "environment": "test_override",
            "redis_url": "redis://test:6379/0",
            "cache_ttl": 600,
        }
        
        with container.config.override(test_config):
            # 验证配置被Override
            assert container.config.environment() == "test_override"
            assert container.config.redis_url() == "redis://test:6379/0"
            assert container.config.cache_ttl() == 600
    
    def test_nested_overrides(self, container):
        """测试嵌套Override"""
        mock_cache_1 = Mock(spec=CacheService)
        mock_cache_1.name = "cache_1"
        
        mock_cache_2 = Mock(spec=CacheService) 
        mock_cache_2.name = "cache_2"
        
        # 嵌套Override
        with container.cache_service.override(providers.Object(mock_cache_1)):
            assert container.cache_service().name == "cache_1"
            
            with container.cache_service.override(providers.Object(mock_cache_2)):
                assert container.cache_service().name == "cache_2"
            
            # 内层Override结束，恢复外层Override
            assert container.cache_service().name == "cache_1"
    
    def test_override_factory_provider(self, container):
        """测试Override Factory Provider"""
        def mock_cache_factory():
            mock_cache = Mock(spec=CacheService)
            mock_cache.factory_created = True
            return mock_cache
        
        # Override为Factory Provider
        with container.cache_service.override(providers.Factory(mock_cache_factory)):
            cache_service = container.cache_service()
            
            # 验证通过Factory创建
            assert hasattr(cache_service, 'factory_created')
            assert cache_service.factory_created is True
    
    def test_override_singleton_provider(self, container):
        """测试Override Singleton Provider"""
        mock_cache = Mock(spec=CacheService)
        mock_cache.singleton_instance = True
        
        # Override为Singleton Provider
        with container.cache_service.override(providers.Singleton(Mock, return_value=mock_cache)):
            cache_service_1 = container.cache_service()
            cache_service_2 = container.cache_service()
            
            # 验证Singleton行为
            assert cache_service_1 is cache_service_2
            assert hasattr(cache_service_1, 'singleton_instance')


@pytest.mark.integration
class TestContainerIntegration:
    """容器集成测试"""
    
    def test_real_services_integration(self):
        """测试真实服务集成"""
        container = Container()
        container.config.from_dict({
            "environment": "testing",
            "market_data_db_url": "sqlite:///test.db",
            "redis_url": "redis://localhost:6379/1",
        })
        
        # 测试服务间依赖关系
        try:
            cache_service = container.cache_service()
            websocket_service = container.websocket_service()
            market_data_service = container.market_data_service()
            
            # 验证服务实例创建成功
            assert cache_service is not None
            assert websocket_service is not None
            assert market_data_service is not None
            
            # 验证服务类型
            assert isinstance(cache_service, CacheService)
            assert isinstance(websocket_service, WebSocketService)
            assert isinstance(market_data_service, MarketDataService)
            
        except Exception as e:
            pytest.fail(f"服务集成测试失败: {e}")
    
    def test_container_wiring(self):
        """测试容器连接"""
        container = Container()
        container.config.from_dict({
            "environment": "testing",
            "market_data_db_url": "sqlite:///test.db",
            "redis_url": "redis://localhost:6379/1",
        })
        
        # 测试容器连接
        try:
            # 这里应该测试实际的模块连接
            # container.wire(modules=["app.api.v1.market_data"])
            pass
        except Exception as e:
            pytest.fail(f"容器连接测试失败: {e}")
